<?php

declare(strict_types=1);

namespace App\Order\Service;

use App\Common\Constants\ErrorCode;
use App\Common\Constants\Stakeholder;
use App\Common\Service\BaseService;
use App\Common\Service\Bc;
use App\Order\Model\OrderModel;
use App\Order\Model\ShopFreeOrderModel;
use App\Order\Model\ShopGainOrderInfoModel;
use App\Order\Model\ShopGroupOrderInfoModel;
use App\Order\Model\ShopHolidayOrderInfoModel;
use App\Order\Model\ShopOrderModel;
use App\Order\Model\ShopSolitaireOrderInfoModel;
use App\Resource\Model\CategoryModel;
use App\Resource\Model\ShopGroupModel;
use App\Resource\Model\ShopModel;
use App\Resource\Service\ShopService;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;

class FinancialService extends BaseService
{

    /**
     * @Inject
     * @var Bc
     */
    protected $bc;

    /**
     * @Inject()
     * @var ShopService
     */
    private $shopService;

    /**
     * @Inject()
     * @var OrderGoodsService
     */
    private $orderGoodsService;

    /**
     * @param array $where
     * @param int $perPage
     * @param array|string[] $field
     * @return array
     *
     * 说明：无 type 参数为普通订单，有 type 参数为免单订单
     */
    public function financialOrder(array $where = [], int $perPage = 15, array $field = ['*'], $orderBy = 'time', $order = 'desc')
    {
        $query = isset($where['type']) ? ShopFreeOrderModel::query() : ShopOrderModel::query();
        $params = $this -> conditionParam($where ?? array());
        $list = $query
            ->when($params['shop_id'] ?? 0, function ($query, $shop_id) {
                return $query->whereIn('shop_id', $shop_id);
            })
            ->whereBetween('time', $params['betweenTime'])
            ->orderBy($orderBy, $order)
            ->get();
        if (!$list) {
            return ['code' => ErrorCode::NOT_EXIST];
        }
        $integrationShopInfo = $this -> getShopInfo($list);
        foreach ($list as $key => $vo) {
            $vo->toArray();
            $list[$key]['shop_name'] = $integrationShopInfo['shopListByShopId'][$vo['shop_id']]['shop_name'] ?? '未知店铺';
            $list[$key]['refund_recharge_order_count'] = $vo['kz_refund_recharge_order_count'] + $vo['wx_refund_recharge_order_count'];
            $shopGroupId = $integrationShopInfo['shopListByShopId'][$vo['shop_id']]['shop_group_id'] ?? '';
            $list[$key]['shop_group_name'] = $integrationShopInfo['shopGroup'][$shopGroupId] ?? '';
            if(!array_key_exists('type', $where)){
                $list[$key]['coupon_cut'] = $vo['total_coupon_cut'];
                $list[$key]['refund_recharge'] = $this->bc->math_add((string)$vo['kz_refund_recharge'], (string)$vo['wx_refund_recharge']);
                $list[$key]['receivables_price'] = $this->bc->math_add((string)$this->bc->math_add((string)$vo['recharge_goods_price'], (string)$vo['total_coupon_cut']) ,(string)$vo['recharge_freight_price']);  // 应收金额 = 商品实付金额 + 总优惠金额 + 运费
                $list[$key]['real_recharge_price'] = $this->bc->math_sub((string)$list[$key]['receivables_price'],(string)$list[$key]['coupon_cut']); // 实收金额 = 应收金额 - 优惠
            }

            unset($list[$key]['kz_refund_recharge_order_count']);
            unset($list[$key]['wx_refund_recharge_order_count']);
        }
        return ['code' => ErrorCode::SUCCESS, 'data' => $list];
    }

    /**
     * @param $index
     * @return \Hyperf\Database\Model\Builder
     */
    protected function setSelection($index)
    {
        $type = $index ?? null;
        switch ($type)
        {
            case '0':
                // 及时达订单
                $query = ShopGainOrderInfoModel::query();
                break;
            case '1':
                // 次日达订单
                $query = ShopHolidayOrderInfoModel::query();
                break;
            case '2':
                // 拼团订单
                $query = ShopGroupOrderInfoModel::query();
                break;
            case '3':
                // 接龙订单
                $query = ShopSolitaireOrderInfoModel::query();
                break;
            default:
                $query = ShopOrderModel::query();
        }

        return $query;
    }

    /**
     * @param array $where
     * @return mixed
     */
    public function conditionParam(array $where = [])
    {
        if (!empty($where['shop_id'])) {
            $params['shop_id'] = [$where['shop_id']];
        } elseif (!empty($where['shop_group_id'])) {
            $shops = ShopModel::query()->where(['shop_group_id' => $where['shop_group_id']])->pluck('shop_id')->toArray();
            $shops = !empty($shops) ? $shops : ['-1'];
            $params['shop_id'] = $shops;
        }
        if(array_key_exists('time', $where)){
            $start = $where['time'];
            $end = $where['time'];
        }else{
            $start = $where['start'] ?? date('Y-m-d', time());
            $end = $where['end'] ?? date('Y-m-d', time());
        }

        $params['betweenTime'] = [$start,$end];
        $params['order_source'] = ShopOrderModel::getOrderSource()[$where['order_source'] ?? null] ?? '全部来源';

        return $params;
    }

    /**
     * @param array $where
     * @param string $orderBy
     * @param string $direction
     * @param int|null $type    门店经营对比：1，门店经营对账：null
     *
     * @return array
     */
    public function financialOrderDateTotal(array $where = [], string $orderBy = 'sort', string $direction = 'asc', ?int $type = null)
    {
        if(in_array($orderBy,['receivables_price', 'real_recharge_price', 'gross_profit_receivable', 'gross_profit_net_receipts','original_amount_of_goods'])){
            $orderBy = 'sort';
        }
        $params = $this -> conditionParam($where ?? array());
        $list = $this -> setSelection($where['order_source'] ?? null)
            ->selectRaw('
                   sort,
                  SUM(recharge_order_count) as sum_recharge_order_count,
                  SUM(refund_order_is_whole_count) as sum_refund_order_is_whole_count,
                  SUM(total_coupon_cut) as sum_total_coupon_cut,
                  SUM(recharge_freight_price) as sum_recharge_freight_price,
                  SUM(recharge_goods_price) as sum_recharge_goods_price,
                  SUM(kz_refund_recharge_order_count) as sum_kz_refund_recharge_order_count,
                  SUM(wx_refund_recharge_order_count) as sum_wx_refund_recharge_order_count,
                  SUM(wx_recharge) as sum_wx_recharge,
                  SUM(kz_recharge) as sum_kz_recharge,
                  SUM(wx_refund_recharge) as sum_wx_refund_recharge,
                  SUM(kz_refund_recharge) as sum_kz_refund_recharge,
                  time,
                  shop_id
           ')
            ->when($params['shop_id'] ?? 0, function ($query, $shop_id) {
                return $query->whereIn('shop_id', $shop_id);
            })
            ->whereBetween('time', $params['betweenTime'])
            ->groupBy(['shop_id'])
            ->orderBy($orderBy, $direction)
            ->get();
        if (!$list) {
            return ['code' => ErrorCode::NOT_EXIST];
        }
        $integrationShopInfo = $this -> getShopInfo($list);
        foreach ($list as $key => $vo) {
            $vo->toArray();
            $list[$key]['order_source'] = $params['order_source']; // 订单来源
            $list[$key]['shop_name'] = $integrationShopInfo['shopListByShopId'][$vo['shop_id']]['shop_name'] ?? '未知店铺'; // 店铺名称
            $list[$key]['sum_refund_recharge_order_count'] = $vo['sum_kz_refund_recharge_order_count'] + $vo['sum_wx_refund_recharge_order_count']; // 退款订单数
            $shopGroupId = $integrationShopInfo['shopListByShopId'][$vo['shop_id']]['shop_group_id'] ?? '';
            $list[$key]['shop_group_name'] = $integrationShopInfo['shopGroup'][$shopGroupId] ?? ''; // 店群名称
            $list[$key]['sum_customer_number'] = $vo['sum_recharge_order_count'] - $vo['sum_refund_order_is_whole_count'];    // 客单数 = 订单数 - 整单退订单数
            $list[$key]['coupon_cut'] = $vo['sum_total_coupon_cut'];    // 优惠金额
            $list[$key]['original_amount_of_goods'] = $this->bc->math_add((string)$vo['sum_recharge_goods_price'], (string)$vo['sum_total_coupon_cut']); // 商品原金额 = 商品实付金额 + 总优惠金额
            $list[$key]['refund_recharge'] = $this->bc->math_add((string)$vo['sum_kz_refund_recharge'], (string)$vo['sum_wx_refund_recharge']); // 退款金额
            $list[$key]['receivables_price'] = $this->bc->math_add((string)$list[$key]['original_amount_of_goods'], (string)$vo['sum_recharge_freight_price']);  // 应收金额 = 商品原金额 + 运费
            $list[$key]['real_recharge_price'] = $this->bc->math_sub((string)$list[$key]['receivables_price'],(string)$list[$key]['coupon_cut']); // 实收金额 = 应收金额 - 优惠
            $list[$key]['truth_real_recharge_price'] = $this->bc->math_sub((string)$list[$key]['real_recharge_price'], (string)$list[$key]['refund_recharge']);  // 实际实收金额 = 实收金额 - 退款金额
            $list[$key]['sum_customer_price'] = $this->bc->math_div((string)$list[$key]['truth_real_recharge_price'],(string)$list[$key]['sum_customer_number']) ?? '0.00';    // 客单价 = 实际实收金额 / 客单数

            if($type == 1){
                $list[$key]['cost_price'] = '0.00';  // 成本金额
                $list[$key]['gross_profit_receivable'] = $this->bc->math_sub((string)$list[$key]['receivables_price'], (string)$list[$key]['cost_price']);  // 应收毛利 = 应收金额 - 成本金额
                $list[$key]['gross_profit_net_receipts'] = $this->bc->math_sub((string)$list[$key]['real_recharge_price'], (string)$list[$key]['cost_price']);  // 实收毛利 = 实收金额 - 成本金额
                $list[$key]['gross_profit_margin_receivable'] = $this->bc->math_div((string)$list[$key]['gross_profit_receivable'], (string)$list[$key]['receivables_price']) ?? '0.00';  // 应收毛利率 = 应收毛利 / 应收金额
                $list[$key]['gross_profit_margin_net_receipts'] = $this->bc->math_div((string)$list[$key]['gross_profit_net_receipts'], (string)$list[$key]['real_recharge_price']) ?? '0.00';  // 实收毛利率 = 实收毛利 / 实收金额
            }

            unset($list[$key]['sum_kz_refund_recharge_order_count']);
            unset($list[$key]['sum_wx_refund_recharge_order_count']);
        }

        return ['code' => ErrorCode::SUCCESS, 'data' => $list];
    }

    /**
     * @param array $where
     * @param string $orderBy
     * @param string $direction
     * @return array
     */
    public function storeOperationMom(array $where = [], string $orderBy = 'sort', string $direction = 'desc')
    {
        $params = $this -> conditionParam($where ?? array());
        $list = $this -> setSelection($where['order_source'] ?? null)
            ->selectRaw('
                  time,
                  shop_id,
                  recharge_order_count,
                  recharge_goods_price,
                  customer_price,
                  recharge,
                  recharge_freight_price,
                  total_coupon_cut,
                  kz_refund_recharge_order_count,
                  wx_refund_recharge_order_count,
                  kz_refund_recharge,
                  wx_refund_recharge,
                  refund_order_is_whole_count
           ')
            ->when($params['shop_id'] ?? 0, function ($query, $shop_id) {
                return $query->whereIn('shop_id', $shop_id);
            })
            ->whereBetween('time', $params['betweenTime'])
            ->orderBy('time','desc')
            ->oldest('sort')
            ->get();
        if (!$list) {
            return ['code' => ErrorCode::NOT_EXIST];
        }
        $integrationShopInfo = $this -> getShopInfo($list);
        foreach ($list as $key => $vo) {
            $vo->toArray();
            $list[$key]['order_source'] = $params['order_source']; // 订单来源
            $list[$key]['shop_name'] = $integrationShopInfo['shopListByShopId'][$vo['shop_id']]['shop_name'] ?? '未知店铺'; // 店铺名称
            $list[$key]['refund_recharge_order_count'] = $vo['kz_refund_recharge_order_count'] + $vo['wx_refund_recharge_order_count']; // 退款订单数
            $shopGroupId = $integrationShopInfo['shopListByShopId'][$vo['shop_id']]['shop_group_id'] ?? '';
            $list[$key]['shop_group_name'] = $integrationShopInfo['shopGroup'][$shopGroupId] ?? ''; // 店群名称
            $list[$key]['total_coupon_cut'] = $vo['total_coupon_cut'];    // 优惠金额
            $list[$key]['refund_recharge'] = $this->bc->math_add((string)$vo['kz_refund_recharge'], (string)$vo['wx_refund_recharge']); // 退款金额
            $list[$key]['original_amount_of_goods'] = $this->bc->math_add((string)$vo['recharge_goods_price'], (string)$vo['total_coupon_cut']); // 商品原金额 = 商品实付金额 + 总优惠金额
            $list[$key]['customer_number'] = $vo['recharge_order_count'] - $vo['refund_order_is_whole_count'];    // 客单数 = 订单数 - 整单退订单数
            $list[$key]['receivables_price'] = $this->bc->math_add((string)$list[$key]['original_amount_of_goods'], (string)$vo['recharge_freight_price']);  // 应收金额 = 商品原金额 + 运费
            $list[$key]['real_recharge_price'] = $this->bc->math_sub((string)$list[$key]['receivables_price'], (string)$list[$key]['total_coupon_cut']); // 实收金额 = 应收金额 - 优惠
            $list[$key]['truth_real_recharge_price'] = $this->bc->math_sub((string)$list[$key]['real_recharge_price'], (string)$list[$key]['refund_recharge']);  // 实际实收金额 = 实收金额 - 退款金额
            $list[$key]['customer_price'] = $this->bc->math_div((string)$list[$key]['truth_real_recharge_price'],(string)$list[$key]['customer_number']) ?? '0.00';    // 客单价 = 实际实收金额 / 客单数
            $list[$key]['cost_price'] = '0.00';  // 成本金额
            $list[$key]['gross_profit_receivable'] = $this->bc->math_sub((string)$list[$key]['receivables_price'], (string)$list[$key]['cost_price']);  // 应收毛利 = 应收金额 - 成本金额
            $list[$key]['gross_profit_net_receipts'] = $this->bc->math_sub((string)$list[$key]['real_recharge_price'], (string)$list[$key]['cost_price']);  // 实收毛利 = 实收金额 - 成本金额
            $list[$key]['gross_profit_margin_receivable'] = $this->bc->math_div((string)$list[$key]['gross_profit_receivable'], (string)$list[$key]['receivables_price']) ?? '0.00';  // 应收毛利率 = 应收毛利 / 应收金额
            $list[$key]['gross_profit_margin_net_receipts'] = $this->bc->math_div((string)$list[$key]['gross_profit_net_receipts'], (string)$list[$key]['real_recharge_price']) ?? '0.00';  // 实收毛利率 = 实收毛利 / 实收金额

            unset($list[$key]['sum_kz_refund_recharge_order_count']);
            unset($list[$key]['sum_wx_refund_recharge_order_count']);
        }
        return ['code' => ErrorCode::SUCCESS, 'data' => $list];
    }

    /**
     * 获取店铺和店群信息
     * @param object $obj
     * @return array
     */
    public function getShopInfo(object $obj)
    {
        $listArr = $obj->toArray();
        // 店铺信息
        $shopIdsArr = array_unique(array_column($listArr, 'shop_id'));
        $shopList = ShopModel::query()->whereIn('shop_id', $shopIdsArr)->select(['shop_id', 'shop_name', 'shop_tel', 'shop_desc', 'shop_group_id'])->get()->toArray();
        // 店群信息
        $shopGroupArr = array_unique(array_column($shopList, 'shop_group_id'));
        $shopGroup = ShopGroupModel::query()->whereIn('id', $shopGroupArr)->select(['shop_group_name', 'id'])->get()->toArray();
        $shopGroup = array_unique(array_column($shopGroup, 'shop_group_name', 'id'));
        $shopListByShopId = array_column($shopList, null, 'shop_id');

        return [
            'shopGroup' => $shopGroup,
            'shopListByShopId' => $shopListByShopId
        ];
    }


    /**
     * 订单数据分析===>全部合计
     * @param string $type
     * @return array
     */
//    public function financialOrderTotal(string $type = '')
//    {
//        $selectRaw = 'SUM(recharge_order_count) as total_recharge_order_count,SUM(customer_price) as total_customer_price,
//                    SUM(recharge_freight_price) as total_recharge_freight_price,SUM(total_coupon_cut) as total_coupon_cut,SUM(recharge) as total_recharge,
//                    SUM(kz_refund_recharge_order_count + wx_refund_recharge_order_count) as total_refund_recharge_order_count,
//                    SUM(kz_refund_recharge) as total_kz_refund_recharge,
//                    SUM(wx_refund_recharge) as total_wx_refund_recharge,
//                    SUM(kz_refund_recharge + wx_refund_recharge) as total_refund_recharge,SUM(recharge_goods_price) as total_recharge_goods_price,
//                    SUM(wx_recharge) as total_wx_recharge,SUM(kz_recharge) as total_kz_recharge,
//                    SUM(recharge - wx_refund_recharge - kz_refund_recharge) as total_real_recharge_price
//                    ';
//        if ($type == '1') {
//            $res = ShopOrderModel::query()
//                ->selectRaw($selectRaw)
//                ->first();
//        } else {
//            $res = ShopOrderModel::query()
//                ->selectRaw($selectRaw)
//                ->whereDate('time', date('Y-m-d'))
//                ->first();
//        }
//        return ['code' => ErrorCode::SUCCESS, 'data' => $res];
//    }

    /**
     * @param array $params
     * @return array
     * @author liule
     */
    public function financialGoods(array $params = [])
    {
        if (!empty($params['shop_id'])) {
            // 门店名称  //店群名称
            $shopInfo = $this->shopService->getInfoById((int)$params['shop_id']);
        }

        $list = $this->orderGoodsService->goodsDataAnalysis($params);

        foreach ($list as $k => $v) {
            $list[$k]['shop_id'] = $shopInfo['data']['shop_id'] ?? '';
            $list[$k]['shop_name'] = $shopInfo['data']['shop_name'] ?? '全部门店';
            $list[$k]['shop_group'] = $shopInfo['data']['group_name'] ?? '--';
            $list[$k]['cost'] = '--';     // 成本金额
            $list[$k]['receivable_profit'] = '--';     // 应收毛利
            $list[$k]['actually_profit'] = '--';     // 实收毛利
            $list[$k]['receivable_profit_rate'] = '--';     // 应收毛利率
            $list[$k]['actually_profit_rate'] = '--';     // 实收毛利率
        }
        return $list;
    }

    /**
     * @param array $params
     *
     * @return array
     */
    public function financialGoodsTotal(array $params)
    {
        if (!empty($params['shop_id'])) {
            $shop_id = [$params['shop_id']];
        } elseif (!empty($params['shop_group_id'])) {
            $shop_id = ShopModel::query()->where(['shop_group_id' => $params['shop_group_id']])->pluck('shop_id')->toArray();
        } else {
            $shop_id = [];
        }
        $list = Db::table('store_order_goods as goods')
            ->leftJoin('store_order as order', 'goods.order_no', '=', 'order.order_no')
            ->leftJoin('store_goods', 'goods.goods_id', '=', 'store_goods.id')
            ->selectRaw('goods.goods_id,goods.cate_id,goods.shop_id,
            SUM(goods.number) as sell_number,
            SUM(goods.dis_price) as real_pay_price,
            SUM(goods.selling_price) as total_selling_price,
            goods.selling_price,
            goods.deductMoney')
            ->where('order.is_pay', '=', '1')
            ->where('order.status', '<>', 5)
            ->when($params['start_time'] ?? 0, function ($query, $start) {
                return $query->whereDate('goods.create_at', '>=', $start);
            })
            ->when($params['end_time'] ?? 0, function ($query, $end) {
                return $query->whereDate('goods.create_at', '<=', $end);
            })
            ->when($shop_id, function ($query, $shop_id) {
                return $query->whereIn('goods.shop_id', $shop_id);
            })
            ->when($params['cate_id'] ?? 0, function ($query, $params) {
                return $query->where('goods.cate_id', $params['cate_id']);
            })
            ->when($is_new ?? 0, function ($query, $is_new) {
                if ($is_new == 1) {
                    return $query->whereRaw('DATE_SUB(sysdate(), INTERVAL 1 month) <= store_goods.create_at');
                } elseif ($is_new == 2) {
                    return $query->whereRaw('DATE_SUB(sysdate(), INTERVAL 1 month) > date(store_goods.create_at)');
                }
            })
            ->groupBy(['goods.goods_id'])
            ->get();
        $listArr = $list->toArray();
        $res = [];
        foreach ($listArr as $key => $val) {
            $res[$key]['sales_volume'] = $val->sell_number;
            $res[$key]['gross'] = 0;
            $res[$key]['percentage'] = 0;
            $res[$key]['price_market'] = $val->total_selling_price;
            $res[$key]['order_discount'] = $val->deductMoney ?? 0;
            $res[$key]['price_selling'] = $val->real_pay_price;
        }
        $result = [];
        $result['total_sales_volume'] = array_sum(array_column($res, 'sales_volume'));
        $result['total_sales_gross'] = '-';
        $result['total_percentage'] = '-';
        $result['total_price_market'] = round(array_sum(array_column($res, 'price_market')), 2);
        $result['total_order_discount'] = round(array_sum(array_column($res, 'order_discount')), 2);
        $result['total_price_selling'] = round(array_sum(array_column($res, 'price_selling')), 2);

        return ['code' => ErrorCode::SUCCESS, 'data' => $result];
    }

    /**
     * @param array $params
     * @return array
     */
    public function financialGoodsRank(array $params)
    {
        $list = Db::table('store_order_goods as goods')
            ->leftJoin('store_order as order', 'goods.order_no', '=', 'order.order_no')
            ->selectRaw('goods.cate_id,goods.goods_id, goods.goods_title as title,goods.create_at,
            SUM(goods.number) as number,
            COUNT(goods.mid) as pay_people_num,
            SUM(goods.dis_price) as real_pay_price,
            SUM(goods.deductMoney) as deductMoney')
            ->where('order.is_pay', '=', '1')
            ->where('order.status', '<>', 5)
            ->when($params['start_time'] ?? 0, function ($query, $start) {
                return $query->whereDate('goods.create_at', '>=', $start);
            })
            ->when($params['end_time'] ?? 0, function ($query, $end) {
                return $query->whereDate('goods.create_at', '<=', $end);
            })
            ->groupBy(['goods.goods_id'])
            ->orderBy('number', 'desc')
            ->limit(20)
            ->get();
        $listArr = $list->toArray();
        $cateIds = array_unique(array_column($listArr, 'cate_id'));
        $category = CategoryModel::query()->whereIn('id', $cateIds)->pluck('title', 'id')->toArray();
        $res = [];
        foreach ($listArr as $key => $val) {
            $res[$key]['create_at'] = $val->create_at;   //订单时间
            $res[$key]['rank_id'] = $key + 1;  //排名
            $res[$key]['goods_cate'] = $category[$val->cate_id];   //商品分类
            $res[$key]['goods_title'] = $val->title;   //商品名称
            $res[$key]['goods_count'] = $val->number;  //订单商品数量
            // 支付人数
            $res[$key]['day_pay_people_num'] = $val->pay_people_num ?? 0;
            // 优惠金额
            $res[$key]['discount_money'] = $val->deductMoney ?? 0;
            // 商品实付金额
            $res[$key]['price_selling'] = $val->real_pay_price ?? 0;
            //客单价 = 销售额/顾客数
            $res[$key]['ave_money'] = $this->bc->math_div($res[$key]['price_selling'], $res[$key]['day_pay_people_num']);
        }
        if ($list) {
            return ['code' => ErrorCode::SUCCESS, 'data' => $res];
        } else {
            return ['code' => ErrorCode::NOT_EXIST];
        }
    }
}
